﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BiliBiliCSharpStudy.old {
    class DelegateDemo3 {
        public static void Demo() {
            Test1();
        }

        public static void Test1() {
            ProductFactory1 prodFactory = new ProductFactory1();
            WrapFactory1 wrapFactory = new WrapFactory1();

            Func<Product1> func1 = new Func<Product1>(prodFactory.MakePizza);
            Func<Product1> func2 = new Func<Product1>(prodFactory.MakeToyCar);

            Logger1 logger = new Logger1();
            Action<Product1> log = new Action<Product1>(logger.Log);

            Box1 box1 = wrapFactory.WrapProduct(func1, log);
            Box1 box2 = wrapFactory.WrapProduct(func2, log);

            Console.WriteLine(box1.Product.Name);
            Console.WriteLine(box2.Product.Name);
        }
    }

    class Logger1 {
        public void Log(Product1 prod) {
            Console.WriteLine("Product '{0}' create at {1}. Price is {2}",
                prod.Name, DateTime.UtcNow, prod.Price);
        }
    }


    class Product1 {
        public string Name { get; set; }
        public double Price { get; set; }
    }

    class Box1 {
        public Product1 Product { get; set; }
    }

    class WrapFactory1 {
        /**
         * Reuse, 重复使用，也叫“复用”。代码的复用不但可以提高工作效率，
         * 还可以减少bug的引入。
         * 良好的复用结构是所有优秀软件所共同追求的目标之一。
         */
        public Box1 WrapProduct(Func<Product1> getProduct, Action<Product1> logCallback) {
            Box1 box = new Box1();
            Product1 product1 = getProduct.Invoke();
            box.Product = product1;
            if (product1.Price >= 50) {
                logCallback(product1);
            }
            return box;
        }
    }

    class ProductFactory1 {
        public Product1 MakePizza() {
            Product1 product1 = new Product1();
            product1.Name = "Pizza";
            product1.Price = 12;
            return product1;
        }
        public Product1 MakeToyCar() {
            Product1 product1 = new Product1() { Name = "Toy Car", Price = 100 };
            return product1;
        }
    }
}
